{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.\n",
    "SPDX-License-Identifier: Apache-2.0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Using Gremlin to Access the Graph\n",
    "\n",
    "The following tutorial walks you through using Gremlin to add vertices, edges, properties, and more to a Neptune graph, highlights some differences in the Neptune-specific Gremlin implementation."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "1. **Add Vertex with label and property**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin\n",
    "\n",
    "g.addV('person').property('name', 'justin')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The vertex is assigned a string ID containing a GUID. All vertex IDs are strings in Neptune.\n",
    "\n",
    "2. **Add a vertex with a custom id**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": true
   },
   "outputs": [],
   "source": [
    "%%gremlin\n",
    "\n",
    "g.addV('person').property(id, '1').property('name', 'martin')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The id property is not quoted. It is a keyword for the ID of the vertex. The vertex ID here is a string with the number 1 in it.\n",
    "\n",
    "Normal property names must be contained in quotation marks.\n",
    "\n",
    "3. **Change property or add property if it doesn't exist.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin\n",
    "\n",
    "g.V('1').property(single, 'name', 'marko')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here you are changing the name property for the vertex from the previous step. This removes all existing values from the name property.\n",
    "\n",
    "If you didn't specify single, it instead appends the value to the name property if it hasn't done so already.\n",
    "\n",
    "4. **Add property, but append property if property already has a value.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin\n",
    "\n",
    "g.V('1').property('age', 29)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "Neptune uses set cardinality as the default action.\n",
    "\n",
    "This command adds the age property with the value 29, but it does not replace any existing values.\n",
    "\n",
    "If the age property already had a value, this command appends 29 to the property. For example, if the age property was 27, the new value would be [ 27, 29 ].\n",
    "\n",
    "5. **Add multiple vertices**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin\n",
    "\n",
    "g.addV('person').property(id, '2').property('name', 'vadas').property('age', 27).next()\n",
    "g.addV('software').property(id, '3').property('name', 'lop').property('lang', 'java').next()\n",
    "g.addV('person').property(id, '4').property('name', 'josh').property('age', 32).next()\n",
    "g.addV('software').property(id, '5').property('name', 'ripple').property('lang', 'java').next()\n",
    "g.addV('person').property(id, '6').property('name', 'peter').property('age', 35)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can send multiple statements at the same time to Neptune.\n",
    "\n",
    "Statements can be separated by newline (`'\\n'`), spaces (`' '`), semicolon (`'; '`), or nothing (for example: `g.addV(‘person’).next()g.V()` is valid).\n",
    "\n",
    "**Note**\n",
    "\n",
    "The Gremlin Console sends a separate command at every newline ('\\n'), so they are each a separate transaction in that case. This example has all the commands on separate lines for readability. Remove the newline ('\\n') characters to send it as a single command via the Gremlin Console.\n",
    "\n",
    "All statements other than the last statement must end in a terminating step, such as .next() or .iterate(), or they will not run. The Gremlin Console does not require these terminating steps.\n",
    "\n",
    "All statements that are sent together are included in a single transaction and succeed or fail together."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "6. **Add edges**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin\n",
    "\n",
    "g.V('1').addE('knows').to(__.V('2')).property('weight', 0.5).next()\n",
    "g.addE('knows').from(__.V('1')).to(__.V('4')).property('weight', 1.0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here are two different ways to add an edge.\n",
    "\n",
    "7. **Add the rest of the Modern Graph**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin\n",
    "\n",
    "g.V('1').addE('created').to(__.V('3')).property('weight', 0.4).next()\n",
    "g.V('4').addE('created').to(__.V('5')).property('weight', 1.0).next()\n",
    "g.V('4').addE('created').to(__.V('3')).property('weight', 0.4).next()\n",
    "g.V('6').addE('created').to(__.V('3')).property('weight', 0.2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "8. **Delete a vertex**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin\n",
    "\n",
    "g.V().has('name', 'justin').drop()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "9. **Run a traversal**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin\n",
    "\n",
    "g.V().hasLabel('person')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "10. **Run a Traversal with values (valueMap()).**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin\n",
    "\n",
    "g.V().has('name', 'marko').out('knows').valueMap()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Returns key, value pairs for all vertices that marko “knows.”\n",
    "\n",
    "11. **Specify multiple labels.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin\n",
    "\n",
    "g.addV(\"Label1::Label2::Label3\") "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Neptune supports multiple labels for a vertex. When you create a label, you can specify multiple labels by separating them with `::`.\n",
    "\n",
    "This example adds a vertex with three different labels.\n",
    "\n",
    "The `hasLabel` step matches this vertex with any of those three labels: `hasLabel(\"Label1\")`, `hasLabel(\"Label2\")`, and `hasLabel(\"Label3\")`.\n",
    "\n",
    "The `::` delimiter is reserved for this use only.\n",
    "\n",
    "You **cannot** specify multiple labels in the `hasLabel` step. For example, `hasLabel(\"Label1::Label2\")` does not match anything.\n",
    "\n",
    "12. **Specify Time/date.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin\n",
    "\n",
    "g.V().property(single, 'lastUpdate', datetime('2018-01-01T00:00:00'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Neptune does not support Java Date. Use the `datetime()` function instead. `datetime()` accepts an ISO8061-compliant datetime string.\n",
    "\n",
    "It supports the following formats: `YYYY-MM-DD`, `YYYY-MM-DDTHH:mm`, `YYYY-MM-DDTHH:mm:SS`, and `YYYY-MM-DDTHH:mm:SSZ`.\n",
    "\n",
    "13. **Delete vertices, properties, or edges.**"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin\n",
    "\n",
    "g.V().hasLabel('person').properties('age').drop().iterate()\n",
    "g.V('1').drop().iterate()\n",
    "g.V().outE().hasLabel('created').drop()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Note**\n",
    "\n",
    "The `.next()` step does not work with `.drop()`. Use `.iterate()` instead."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## What's next?\n",
    "\n",
    "Now that you've tried your hand at Gremlin queries, take your learning to the next level with these datasets:\n",
    "\n",
    "[Explore English Premier League using Gremlin](../02-Visualization/EPL-Gremlin.ipynb)\n",
    "\n",
    "[Explore global air route data using Gremlin](../02-Visualization/Air-Routes-Gremlin.ipynb)\n",
    "\n",
    "[Explore social networks using Gremlin](./04-Social-Network-Recommendations-with-Gremlin.ipynb)\n",
    "\n",
    "Curious about the business problems can be solved with graph? Check out these sample application notebooks for some inspiration.\n",
    "\n",
    "[Introduction to Fraud Graphs](../03-Sample-Applications/01-Fraud-Graphs/01-Building-a-Fraud-Graph-Application.ipynb)\n",
    "\n",
    "[Introduction to Knowledge Graphs](../03-Sample-Applications/02-Knowledge-Graphs/01-Building-a-Knowledge-Graph-Application.ipynb)\n",
    "\n",
    "[Introduction to Identity Graphs](../03-Sample-Applications/03-Identity-Graphs/01-Building-an-Identity-Graph-Application.ipynb)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
